package com.wutong.teacher_server.utils;


import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.*;
import org.apache.commons.lang.StringUtils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;

/**
 *  OSS sdk 二次封装
 * @author Yu Dong
 *
 */
public class OssYwUtils {

	public static final String  INPUTSTREAMNULL = "inputStream为null";

	public static final String  YYYYMMDD = "yyyyMMdd";

	public static final String  BUCKETPATH = "officeImgs/";

	public static final String  HTTP = "http://";


	/**
	 * 简单上传文件，随机分配文件名
	 * @param endpoint 访问域名，如oss-cn-shenzhen.aliyuncs.com
	 * @param bucketName 存储空间，https://oss.console.aliyun.com/bucket/oss-cn-shenzhen/youwei-file/overview
	 * @param accessKeyId
	 * @param accessKeySecret
	 * @param inputStream
	 * @param bucketPath bucket目录，传入此参数可指定上传初始目录，如fsd/1/3/321/
	 * @param fileSuffix 文件名后缀，如 .png
	 * @return
	 * @throws Exception
	 */
	public static String simpleUpload(String endpoint,String bucketName,String accessKeyId,String accessKeySecret,
									  FileInputStream inputStream,String bucketPath,String fileSuffix) throws Exception {
		checkNullParam(endpoint,bucketName, accessKeyId, accessKeySecret);
		if (inputStream == null) {
			throw new RuntimeException(INPUTSTREAMNULL);
		}
		if (StringUtils.isEmpty(fileSuffix) || fileSuffix.lastIndexOf('.') != 0) {
			throw new RuntimeException("fileSuffix 参数错误");
		}
		String monthPath = Tools.date2Str(new Date(), YYYYMMDD);
		// 采用时间+UUID的方式随机命名
		String fileName = Tools.snGenerateWithUUID()+fileSuffix;
		bucketPath = dealBucketPath(bucketPath);
		OSSClient ossClient = null;
		try {
			ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
			ossClient.putObject(bucketName, bucketPath+monthPath + "/" + fileName, inputStream);
		} catch (Exception e) {
			if (StringUtils.isEmpty(bucketPath) || !bucketPath.contains(BUCKETPATH)) {
				throw new RuntimeException("OSSClient上传文件异常，请确认参数是否填写正确");
			}
		}finally {
			if(ossClient != null ){
				ossClient.shutdown();
			}
		}
		return HTTP + bucketName + "." + endpoint + "/" + bucketPath + monthPath + "/" + fileName;
	}


	/**
	 * 简单上传文件，随机分配文件名
	 * @param endpoint 访问域名，如oss-cn-shenzhen.aliyuncs.com
	 * @param bucketName 存储空间，https://oss.console.aliyun.com/bucket/oss-cn-shenzhen/youwei-file/overview
	 * @param accessKeyId
	 * @param accessKeySecret
	 * @param inputStream
	 * @param bucketPath bucket目录，传入此参数可指定上传初始目录，如fsd/1/3/321/
	 * @param fileSuffix 文件名后缀，如 .png
	 * @return
	 * @throws Exception
	 */
	public static String simpleUploadHtml(String endpoint,String bucketName,String accessKeyId,String accessKeySecret,
										  FileInputStream inputStream,String bucketPath,String fileSuffix,boolean isHtml) throws Exception {
		checkNullParam(endpoint,bucketName, accessKeyId, accessKeySecret);
		if (inputStream == null) {
			throw new RuntimeException(INPUTSTREAMNULL);
		}
		if (StringUtils.isEmpty(fileSuffix) || fileSuffix.lastIndexOf('.') != 0) {
			throw new RuntimeException("fileSuffix 参数错误");
		}
		String monthPath = Tools.date2Str(new Date(), YYYYMMDD);
		// 采用时间+UUID的方式随机命名
		String fileName = Tools.snGenerateWithUUID()+fileSuffix;
		bucketPath = dealBucketPath(bucketPath);
		OSSClient ossClient = null;
		try {
			if (isHtml) {
				ObjectMetadata meta = new ObjectMetadata();
				meta.setContentType("text/html");
				meta.setContentEncoding("utf-8");
			}
			ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
			ossClient.putObject(bucketName, bucketPath+monthPath + "/" + fileName, inputStream);
		} catch (Exception e) {
			if (StringUtils.isEmpty(bucketPath) || !bucketPath.contains(BUCKETPATH)) {
				throw new RuntimeException("OSSClient上传文件异常，请确认参数是否填写正确");
			}
		}finally {
			if(ossClient != null ){
				ossClient.shutdown();
			}
		}

		return "http://oss.youwe-edu.com/" + bucketPath + monthPath + "/" + fileName;
	}


	/**
	 * 简单上传文件，指定上传文件名称
	 * 使用此方法应注意，指定目录和文件名可能会出现覆盖旧文件的情况，建议该方法只用于上传apk及非用户操作的文件
	 * @param endpoint 访问域名，如oss-cn-shenzhen.aliyuncs.com
	 * @param bucketName 存储空间，https://oss.console.aliyun.com/bucket/oss-cn-shenzhen/youwei-file/overview
	 * @param bucketPath bucket目录
	 * @param accessKeyId
	 * @param accessKeySecret
	 * @param inputStream
	 * @param fileName 文件名后缀，如 a.apk
	 * @return
	 * @throws Exception
	 */
	public static String assignPathUpload(String endpoint,String bucketName,String accessKeyId,
										  String accessKeySecret,FileInputStream inputStream,String bucketPath,String fileName) throws Exception {
		checkNullParam(endpoint,bucketName, accessKeyId, accessKeySecret);
		if (inputStream == null) {
			throw new RuntimeException(INPUTSTREAMNULL);
		}
		if (StringUtils.isEmpty(fileName) ) {
			throw new RuntimeException("文件名为空");
		}
		OSSClient ossClient = null;
		try {
			ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
			bucketPath = dealBucketPath(bucketPath);
			ossClient.putObject(bucketName, bucketPath+fileName, inputStream);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("OSSClient上传文件异常，请确认参数是否填写正确");
		}finally {
			if(ossClient != null ){
				ossClient.shutdown();
			}
		}
		return HTTP + bucketName+"."+endpoint+ "/" + bucketPath + fileName;
	}


	/**
	 * 判断文件是否存在
	 * @param endpoint 访问域名，如oss-cn-shenzhen.aliyuncs.com
	 * @param bucketName 存储空间
	 * @param accessKeyId
	 * @param accessKeySecret
	 * @param ossFileName OSS上存储的文件，传入全路径但不含bucketName，例：/first/second/
	 * @throws Exception
	 */
	public static boolean existObject(String endpoint,String bucketName,String accessKeyId,String accessKeySecret,
									  String ossFileName) throws Exception {
		checkNullParam(endpoint,bucketName, accessKeyId, accessKeySecret);
		if (StringUtils.isEmpty(ossFileName)) {
			throw new RuntimeException("ossFileName 参数错误");
		}
		boolean found;
		OSSClient ossClient = null;
		try {
			ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
			found = ossClient.doesObjectExist(bucketName, ossFileName);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("OSSClient初始化异常，请确认参数是否填写正确");
		}finally {
			if(ossClient != null ){
				ossClient.shutdown();
			}
		}
		return found;
	}


	/**
	 * 获取某个目录下所有文件名
	 * @param endpoint 访问域名，如oss-cn-shenzhen.aliyuncs.com
	 * @param bucketName 存储空间，仅bucket名，后面勿跟目录
	 * @param accessKeyId
	 * @param accessKeySecret
	 * @param directoryPath object目录，不包含bucket，不要以"/"开头
	 * @param count 获取的object数量，默认100，最大1000
	 * @return
	 * @throws Exception
	 */
	public static ArrayList<String> listObjects(String endpoint,String bucketName,String accessKeyId,
												String accessKeySecret,String directoryPath,Integer count) throws Exception {
		checkNullParam(endpoint,bucketName, accessKeyId, accessKeySecret);
		ArrayList<String> list = new ArrayList<String>();
		OSSClient ossClient = null;
		try {
			ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
			ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
			if (StringUtils.isNotEmpty(directoryPath)) {
				listObjectsRequest.setPrefix(directoryPath);
			}
			if (count != null ) {
				if (count < 1) {
					count = 100;
				}else if(count > 1000) {
					count = 1000;
				}
				listObjectsRequest.setMaxKeys(count);
			}
			ObjectListing listing = ossClient.listObjects(listObjectsRequest);
			String temp = null;
			for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
				temp = HTTP + bucketName+"."+endpoint+"/"+objectSummary.getKey();
				list.add(temp);
			}
		} catch (Exception e) {
			throw new RuntimeException("OSSClient下载文件异常，请确认参数是否填写正确");
		}finally {
			if(ossClient != null ){
				ossClient.shutdown();
			}
		}
		return list;
	}

	/**
	 * 下载文件到本地
	 * @param endpoint 访问域名，如oss-cn-shenzhen.aliyuncs.com
	 * @param bucketName 存储空间，若要下载bucket下的带目录的文件，则需要传入全路径，例：/bucket-file/first/second/
	 * @param accessKeyId
	 * @param accessKeySecret
	 * @param ossFilePath object树形目录，不包含bucket，不要以"/"开头
	 * @param localPath 本地具体路径，如 E:\\imgtemp\\1.png
	 * throws Exception
	 */
	public static void downloadObject(String endpoint,String bucketName,String accessKeyId,
									  String accessKeySecret,String ossFilePath,String localPath) throws Exception {
		OSSClient ossClient = null;
		try {
			ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
			ossClient.getObject(new GetObjectRequest(bucketName, ossFilePath), new File(localPath));
		} catch (Exception e) {
			throw new RuntimeException("OSSClient下载文件异常，请确认参数是否填写正确");
		}finally {
			if(ossClient != null ){
				ossClient.shutdown();
			}
		}
	}





	/**
	 * 校验基础参数
	 * @param bucketName
	 * @param accessKeyId
	 * @param accessKeySecret
	 * @param
	 * @throws Exception
	 */
	private static void checkNullParam(String endpoint,String bucketName, String accessKeyId,
									   String accessKeySecret)
			throws Exception {
		if (StringUtils.isEmpty(endpoint) || StringUtils.isEmpty(bucketName)
				|| StringUtils.isEmpty(accessKeyId) || StringUtils.isEmpty(accessKeySecret)	) {
			throw new RuntimeException("OSS基础参数异常，请检查前4个参数");
		}
	}

	/**
	 * 处理OSS上的路径
	 * @param bucketPath
	 * @return
	 */
	private static String dealBucketPath(String bucketPath) {
		if (!StringUtils.isEmpty(bucketPath) && bucketPath.length() > 2) {
			if (!bucketPath.endsWith("/")) {
				bucketPath = bucketPath+"/";
			}
			if (bucketPath.startsWith("/")) {
				bucketPath = bucketPath.substring(1,bucketPath.length());
			}
			return bucketPath;
		}
		return null;
	}

	public static String uploadBase64Img(String endpoint,String bucketName,String accessKeyId,String accessKeySecret,
										 String bucketPath ,String imgBase64  ) {
		String monthPath = Tools.date2Str(new Date(), YYYYMMDD);
		// 采用时间+UUID的方式随机命名
		String fileName = Tools.snGenerateWithUUID()+".jpg";
		bucketPath = dealBucketPath(bucketPath);
		OSSClient ossClient = null;
		try {

			bucketPath = dealBucketPath(bucketPath);
			//因为有的base64生成的时候前面会有前缀。这里是为了去掉，不然传上去变不成图片
			//imgBase64 = imgBase64.split(",")[1];
			//将生成的base64码反编译回二进制字节码
			sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
			byte[] file = decoder.decodeBuffer(imgBase64);
			ObjectMetadata objectMeta = new ObjectMetadata();
			objectMeta.setContentLength(file.length);
			//将字节码转换成流
			InputStream input = new ByteArrayInputStream(file);

			ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
			ossClient.putObject(bucketName, bucketPath+monthPath + "/" + fileName, input, objectMeta);

		}catch (Exception e){
			if (StringUtils.isEmpty(bucketPath) || !bucketPath.contains(BUCKETPATH)) {
				throw new RuntimeException("OSSClient上传文件异常，请确认参数是否填写正确");
			}
		}finally {
			if(ossClient != null ){
				ossClient.shutdown();
			}

		}
		return HTTP + bucketName + "." + endpoint + "/" + bucketPath + monthPath + "/" + fileName;
	}


	public static String uploadExcelByStream(String endpoint,String bucketName,String accessKeyId,String accessKeySecret,
											 String bucketPath ,InputStream in,Integer length) {
		String monthPath = Tools.date2Str(new Date(), YYYYMMDD);
		// 采用时间+UUID的方式随机命名
		String fileName = Tools.snGenerateWithUUID()+".xls";
		bucketPath = dealBucketPath(bucketPath);
		OSSClient ossClient = null;
		try {

			bucketPath = dealBucketPath(bucketPath);

			ObjectMetadata objectMeta = new ObjectMetadata();
			objectMeta.setContentLength(length);


			ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
			ossClient.putObject(bucketName, bucketPath+monthPath + "/" + fileName, in, objectMeta);

		}catch (Exception e){
			if (StringUtils.isEmpty(bucketPath) || !bucketPath.contains(BUCKETPATH)) {
				throw new RuntimeException("OSSClient上传文件异常，请确认参数是否填写正确");
			}
		}finally {
			if(ossClient != null ){
				ossClient.shutdown();
			}

		}
		return "http://" + bucketName + "." + endpoint + "/" + bucketPath + monthPath + "/" + fileName;
	}



}
